package com.boot.security.server.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.boot.security.server.contant.Constant;
import com.boot.security.server.dict.mapper.DataDictDetailsMapper;
import com.boot.security.server.dto.UserDto;
import com.boot.security.server.page.table.PageTableHandler;
import com.boot.security.server.page.table.PageTableRequest;
import com.boot.security.server.page.table.PageTableResponse;
import com.boot.security.server.user.dao.UserDao;
import com.boot.security.server.user.model.SysUsers;
import com.boot.security.server.user.model.SysUsers.Status;
import com.boot.security.server.user.service.UserService;
import com.google.common.base.Joiner;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author king
 */
@Service
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger("adminLogger");
    private static final int FIVE = 5;
    private static final int FOUR = 4;

    @Autowired
    private UserDao userDao;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private DataDictDetailsMapper detailsMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUsers saveUser (UserDto userDto) {
        List<String> branchList = Arrays.asList(userDto.getBranch().split(","));
        List<Long> roleIds = userDto.getRoleIds();
        if (CollectionUtils.isNotEmpty(branchList)) {
            branchList.forEach(branch -> {
                if (CollectionUtils.isNotEmpty(roleIds)) {
                    roleIds.forEach(id -> {
                        if (id == FIVE) {
                            List<SysUsers> reviewUsers = userDao.findUserByLikeBranchAndReview(branch);
                            updateUser(branch, reviewUsers);
                        }
                        if (id == FOUR) {
                            List<SysUsers> superviseUsers = userDao.findUserByLikeBranchAndSupervise(branch);
                            updateUser(branch, superviseUsers);
                        }
                    });
                }
            });
        }
        SysUsers user = userDto;
        user.setMwPassword(user.getPassword());
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setStatus(Status.VALID);
        userDao.save(user);
        saveUserRoles(user.getId(), roleIds);
        log.debug("新增用户{}", user.getUsername());
        return user;
    }

    private void updateUser (String branch, List<SysUsers> users) {
        if (CollectionUtils.isNotEmpty(users)) {
            users.forEach(user -> {
                List<String> ss = Arrays.asList(user.getBranch().split(","));
                List<String> sss = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(ss)) {
                    for (String s : ss) {
                        if (! StringUtils.equals(s, branch)) {
                            sss.add(s);
                        }
                    }
                }
                user.setBranch(Joiner.on(",").join(sss));
                userDao.update(user);
            });
        }
    }

    private void saveUserRoles (Long userId, List<Long> roleIds) {
        if (roleIds != null) {
            userDao.deleteUserRole(userId);
            if (! CollectionUtils.isEmpty(roleIds)) {
                userDao.saveUserRoles(userId, roleIds);
            }
        }
    }

    @Override
    public SysUsers getUser (String username) {
        return userDao.getUser(username);
    }
    @Override
    public SysUsers getUserByOa (String username) {
        return userDao.getUserByOa(username);
    }

    @Override
    public void changePassword (String username, String oldPassword, String newPassword) {
        SysUsers u = userDao.getUser(username);
        if (u == null) {
            throw new IllegalArgumentException("用户不存在");
        }

        if (! passwordEncoder.matches(oldPassword, u.getPassword())) {
            throw new IllegalArgumentException("旧密码错误");
        }

        userDao.changePassword(u.getId(), passwordEncoder.encode(newPassword), newPassword);

        log.debug("修改{}的密码", username);
    }

    @Override
    public SysUsers enDis (Long id) {
        SysUsers user = userDao.getById(id);
        int status = user.getStatus() == 1 ? 0 : 1;
        user.setStatus(status);
        userDao.update(user);
        log.info("启用/禁用");
        return user;
    }

    @Override
    public PageTableResponse listUsers (PageTableRequest request) {
        if (request.getParams().get(Constant.BRANCH) != null && request.getParams().get(Constant.BRANCH) != "") {
            String branch =  request.getParams().get(Constant.BRANCH).toString();
            List<String> type = JSONObject.parseArray(branch, String.class);
            request.getParams().put(Constant.BRANCH, type);
        } else {
            request.getParams().remove(Constant.BRANCH);
        }
        return new PageTableHandler(new PageTableHandler.CountHandler() {
            @Override
            public int count (PageTableRequest request) {
                return userDao.count(request.getParams());
            }
        }, new PageTableHandler.ListHandler() {
            @Override
            public List<SysUsers> list (PageTableRequest request) {
                List<SysUsers> list = userDao.list(request.getParams(), request.getOffset(), request.getLimit());
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(user -> {
                        if (StringUtils.isNotEmpty(user.getBranch())) {
                            List<String> ss = Arrays.asList(user.getBranch().split(","));
                            List<String> sss = new ArrayList<>();
                            ss.forEach(s -> {
                                String value = detailsMapper.findDataValueByDataKeyAndDictId(s, 3);
                                sss.add(value);
                            });
                            user.setBranch(Joiner.on(",").join(sss));
                        }
                    });
                }
                return list;
            }
        }).handle(request);
    }

    @Override
    public SysUsers getById (Long id) {
        SysUsers user = userDao.getById(id);
        if (StringUtils.isNotBlank(user.getBranch())) {
            user.setBranchs(Arrays.asList(user.getBranch().split(",")));
        }
        return user;
    }

    @Override
    public List<SysUsers> getByPid(Integer userId) {

        return userDao.getByPid(userId);

    }

    @Override
    public String getUserName(String oversee) {
        return userDao.getUserName(oversee);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUsers updateUser (UserDto userDto) {
        List<String> branchList = Arrays.asList(userDto.getBranch().split(","));
        List<Long> roleIds = userDto.getRoleIds();
        if (CollectionUtils.isNotEmpty(branchList)) {
            branchList.forEach(branch -> {
                if (CollectionUtils.isNotEmpty(roleIds)) {
                    roleIds.forEach(id -> {
                        if (id == FIVE) {
                            List<SysUsers> reviewUsers = userDao.findUserByLikeBranchAndReviewAndId(branch, userDto.getId());
                            updateUser(branch, reviewUsers);
                        }
                        if (id == FOUR) {
                            List<SysUsers> superviseUsers = userDao.findUserByLikeBranchAndSuperviseAndId(branch, userDto.getId());
                            updateUser(branch, superviseUsers);
                        }
                    });
                }
            });
        }
        userDao.update(userDto);
        saveUserRoles(userDto.getId(), roleIds);
        return userDto;
    }
}
